package model.led.concurrent;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import model.common.LED;
import model.grove.LEDSocket;

import org.junit.Test;

import framework.common.ModelFactory;
import framework.common.MultiSensor;
import framework.common.SensorRequest;
//import framework.common.HubServer;
import framework.concurrent.*;

public class LEDTest {
	private ModelFactory factory = new ModelFactory(ModelFactory.CONCURRENT);

	/**
	 * 未登録デバイスへアクセスしようとしてエラーになるケース
	 */
	@Test
	public void testLED0a() {
		// Hubサーバを起動する
		HubServer hub = new HubServer();
		//hub.start(); // HubServerはpassiveなのでスレッドで動かす必要がない

		// ユーザAがLED0をHubサーバに登録する
		DeviceServer da = new DeviceServer("A'LED0");
		da.setSensor(new LEDSocket());
		da.setHub(hub);
		//da.register("A");
		da.start();

		// Aがクライアントを起動し、LED0に接続する
		Client ca = new LEDClient("A");
		ca.setHub(hub);
		ca.connect(da);

		LED la = (LED)ca;

		// Aの操作
		try {
			la.lightOn();
			fail();
		} catch(RuntimeException e) {
		}
		da.stop();
	}

	/**
	 * 未接続デバイスへアクセスしようとしてエラーになるケース
	 */
	@Test
	public void testLED0b() {
		// Hubサーバを起動する
		HubServer hub = new HubServer();

		// ユーザAがLED0をHubサーバに登録する
		DeviceServer da = new DeviceServer("A'LED0");
		da.setSensor(new LEDSocket());
		da.setHub(hub);
		da.register("A");
		da.start();

		// Aがクライアントを起動し、LED0に接続する
		Client ca = new LEDClient("A");
		ca.setHub(hub);
		//ca.connect(da);

		LED la = (LED)ca;

		// Aの操作
		try {
			la.lightOn();
			fail();
		} catch(RuntimeException e) {
		}
		da.stop();
	}

	/**
	 * センサー未接続のデバイスへアクセスしようとしてエラーになるケース
	 */
	@Test
	public void testLED0c() {
		// Hubサーバを起動する
		HubServer hub = new HubServer();

		// ユーザAがLED0をHubサーバに登録する
		DeviceServer da = new DeviceServer("A'LED0");
		//da.setSensor(createSensor());
		da.setHub(hub);
		da.register("A");
		da.start();

		// Aがクライアントを起動し、LED0に接続する
		Client ca = new LEDClient("A");
		ca.setHub(hub);
		ca.connect(da);

		LED la = (LED)ca;

		// Aの操作
		try {
			la.lightOn();
			fail();
		} catch(RuntimeException e) {
//			e.printStackTrace();
		}
		da.stop();
	}

	/**
	 * 1ユーザが1デバイスにアクセスするケース
	 */
	@Test
	public void testLED1() {
		// Hubサーバを起動する
		HubServer hub = new HubServer();

		// ユーザAがLED0をHubサーバに登録する
		DeviceServer da = new DeviceServer("A'LED0");
		da.setSensor(new LEDSocket());
		da.setHub(hub);
		da.register("A");
		da.start();

		// Aがクライアントを起動し、LED0に接続する
		Client ca = new LEDClient("A");
		ca.setHub(hub);
		ca.connect(da);

		LEDClient la = (LEDClient)ca;

		// Aの操作
		la.lightOn();
		assertTrue(la.isOn());
		la.lightOff();
		assertTrue(la.isOff());

		da.stop();
	}

	/**
	 * 1ユーザが2センサの1デバイスにアクセスするケース
	 */
	@Test
	public void testLED1a() {
		// Hubサーバを起動する
		HubServer hub = new HubServer();
		hub.start();

		// センサ
		MultiSensor ms = new MultiSensor();
		ms.attach("a", new LEDSocket());
		ms.attach("b", new LEDSocket());

		// ユーザAがLED0をHubサーバに登録する
		DeviceServer da = new DeviceServer("A'hub");
		da.setSensor(ms);
		da.setHub(hub);
		da.register("A");
		da.start();

		// Aがクライアントを起動し、LED0に接続する
		Client ca = new LEDClient("A");
		ca.setHub(hub);
		ca.connect(da);

		// Aの操作
		ca.begin();
		ca.addRequest(SensorRequest.SET, "a.LED",1);
		ca.end();
		ca.request();
		ca.begin();
		ca.addRequest(SensorRequest.SET, "b.LED",1);
		ca.end();
		ca.request();

		da.stop();
		hub.stop();
	}

	// TODO not implemented yet

}
